package com.nega.modules.handler;

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.nega.commons.model.MemberUser;
import com.nega.commons.model.SearchResult;
import com.nega.commons.util.DataUtil;
import com.nega.commons.util.DateUtils;
import com.nega.modules.service.ConfigService;
import com.nega.modules.service.MemberUserService;
import com.nega.modules.service.SearchCenterService;
import com.nega.modules.service.SearchResultService;
import com.nega.modules.service.SpiderService;
import com.nega.modules.thread.SpiderThreadResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.TreeSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * @Author: Garcia
 * @CreateDate: 2019/5/10 0:01
 * @Description: 舆情搜索中心
 */
@Slf4j
public class SearchCenterServiceImpl implements SearchCenterService {

    private List<SpiderService> spiderServices;

    @Resource
    private ConfigService configService;

    @Resource
    private MemberUserService memberUserService;

    @Resource
    private SearchResultService searchResultService;

    @Override
    public List<SearchResult> search(String text) {

        if (StringUtils.isBlank(text)) {
            return new ArrayList<>();
        }

        //查询是否已存在资源
        List<SearchResult> data = searchResultService.getListByText(text);
        if (data!=null && data.size()>0){
            //会员制度处理
            List<SearchResult> vips = vipProcess(data);
            return vips;
        }

        //数据爬取
        List<SearchResult> results = getResult(text);

        //数据分析
        List<SearchResult> datas = analyzeData(results, text);

        //数据入库
        searchResultService.insert(datas);

        //会员制度处理
        List<SearchResult> vips = vipProcess(datas);
        return vips;

    }

    @Override
    public String PDFCreate(List<SearchResult> results) {

        String pdfpath = configService.getProperty("pdfPath");
        MemberUser memberUser = (MemberUser) SecurityUtils.getSubject().getPrincipal();
        String fileName;
        if (memberUser == null) {
            fileName = DataUtil.getRandomData(3) + "-" + DateUtils.date2String(new Date(), DateUtils.YYYYMMDDHHMMSS) + ".pdf";
        } else {
            fileName = memberUser.getEmail() + "-" + DateUtils.date2String(new Date(), DateUtils.YYYYMMDDHHMMSS) + ".pdf";
        }
        String path = pdfpath + File.separator + fileName;
        Document document = new Document();
        document.addTitle("舆情系统PDF报表");
        document.addAuthor("舆情系统");
        try {
            PdfWriter.getInstance(document, new FileOutputStream(path));
            String prefixFont;
            String os = System.getProperties().getProperty("os.name");
            if (os.startsWith("win") || os.startsWith("Win")) {
                prefixFont = "C:\\Windows\\Fonts" + File.separator;
            } else {
                prefixFont = "/usr/share/fonts/chinese" + File.separator;
            }

            // 设置中文字体
            BaseFont bfChinese = BaseFont.createFont(prefixFont + "simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            //字体
            Font titleChinese = new Font(bfChinese, 20, Font.BOLD);
            Font fontChinese = new Font(bfChinese, 8, Font.NORMAL);
            Font red = new Font(bfChinese, 8, Font.NORMAL, BaseColor.RED);
            Font green = new Font(bfChinese, 8, Font.NORMAL, BaseColor.GREEN);

            document.open();
            Paragraph title = new Paragraph("舆情系统报表", titleChinese);
            title.setAlignment(Element.ALIGN_CENTER);
            document.add(title);
            for (SearchResult result : results) {
                Paragraph oneTitle = new Paragraph("标题：", fontChinese);
                Phrase faxTitle1 = null;
                if ("0".equals(result.getLyrical())) {
                    faxTitle1 = new Phrase("●", red);
                } else {
                    faxTitle1 = new Phrase("●", green);
                }
                Phrase faxTitle2 = new Phrase(" ", fontChinese);
                Phrase faxTitle3 = new Phrase(result.getTitle(), fontChinese);
                oneTitle.add(faxTitle1);
                oneTitle.add(faxTitle2);
                oneTitle.add(faxTitle3);
                document.add(oneTitle);

                Paragraph url = new Paragraph("地址：", fontChinese);
                Phrase urlfax = new Phrase(result.getUrl(), fontChinese);
                url.add(urlfax);
                document.add(url);

                Paragraph hengx = new Paragraph("-----------------------------------------------------------", fontChinese);
                document.add(hengx);
            }
            document.close();
        } catch (Exception e) {
            log.error("PDF写出失败", e);
        }

        return fileName;
    }

    private List<SearchResult> vipProcess(List<SearchResult> datas) {

        MemberUser memberUser = (MemberUser) SecurityUtils.getSubject().getPrincipal();
        MemberUser user = null;
        if (memberUser != null) {
            user = memberUserService.getUserById(String.valueOf(memberUser.getId()));
        }
        if (user == null) {
            for (int i = 0; i < datas.size(); i++) {
                if (i < 4) {
                    continue;
                }
                SearchResult result = datas.get(i);
                result.setUrl("#");
                result.setTitle(DataUtil.hiddenData(result.getTitle()));
                result.setContent(DataUtil.hiddenData(result.getContent()));
            }
        } else {
            if (!user.getIsVip()) {
                List<SearchResult> notVIP = new ArrayList<>();
                for (int i = 0; i < 9; i++) {
                    notVIP.add(datas.get(i));
                }
                return notVIP;
            }
        }
        return datas;
    }

    private List<SearchResult> getResult(String text) {
        List<SearchResult> results = new ArrayList<>();
        ExecutorService executorService = Executors.newFixedThreadPool(spiderServices.size());
        List<Future<List<SearchResult>>> futures = new ArrayList<>();
        for (SpiderService spiderService : spiderServices) {
            Future<List<SearchResult>> future = executorService.submit(new SpiderThreadResult(spiderService, text));
            futures.add(future);
        }

        log.info("数据提取>>>>>>>>>>>>");

        long start = System.currentTimeMillis();

        for (Future<List<SearchResult>> future : futures) {
            try {
                List<SearchResult> resu = future.get();
                if (resu.size() < 1) {
                    continue;
                }
                results.addAll(resu);
            } catch (Exception e) {
                log.error("异常读取异常", e);
            } finally {
                executorService.shutdown();
            }
        }

        log.info("数据提取结束，全部耗时:{}", (System.currentTimeMillis() - start));

        return results;
    }

    private List<SearchResult> analyzeData(List<SearchResult> results, String text) {

        log.info("数据解析>>>>>>>>>>>>");

        String firstLevel[] = { "期骗", "diss", "逃税", "漏税", "不雅", "封杀", "犯罪", "强奸", "奸炸", "诈骗", "案件", "出轨", "猛料", "贿赂", "受贿", "丑闻", "性交", "性行", "吸毒", "嫖娼" };

        String secondLevel[] = { "诉讼", "被告", "骂人", "被骂", "涉嫌", "恶心", "禁止", "事件", "处罚", "被罚", "骚扰", "仙人跳", "打人", "家暴", "暴力", "私会", "打架", "投诉" };

        String thirdLevel[] = { "吐槽", "被偷", "抢劫", "犯错", "没落", "黑暗", "黑幕", "调侃", "讽刺" };

        String keyword = "";
        if (text.trim().contains(" ")) {
            String[] texts = text.split(" ");
            keyword = texts[texts.length - 1];
        }

        //去除重复数据
        List<SearchResult> unique = results.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SearchResult::getTitle))), ArrayList::new));

        Date createTime = new Date();
        List<SearchResult> data = new ArrayList<>();

        //指定关键词计算负面值
        if (StringUtils.isNotBlank(keyword)) {
            Iterator<SearchResult> diyKey = unique.iterator();
            while (diyKey.hasNext()) {
                SearchResult su = diyKey.next();
                if (DataUtil.isChinese(keyword)) {
                    for (char word : keyword.toCharArray()) {
                        if (StringUtils.isNotBlank(su.getTitle()) && su.getTitle().contains(String.valueOf(word))) {
                            su.setLyrical("0");
                            su.setNegativeIndex(String.valueOf(DataUtil.getRandomDecimal(80.56, 99.65)));
                            su.setCreateTime(createTime);
                            su.setUpdateTime(createTime);
                            data.add(su);
                            diyKey.remove();
                            break;
                        }
                        if (StringUtils.isNotBlank(su.getContent()) && su.getContent().contains(String.valueOf(word))) {
                            su.setLyrical("0");
                            su.setNegativeIndex(String.valueOf(DataUtil.getRandomDecimal(60.56, 90.65)));
                            su.setCreateTime(createTime);
                            su.setUpdateTime(createTime);
                            data.add(su);
                            diyKey.remove();
                            break;
                        }
                    }
                } else {
                    if (StringUtils.isNotBlank(su.getTitle()) && su.getTitle().contains(keyword)) {
                        su.setLyrical("0");
                        su.setNegativeIndex(String.valueOf(DataUtil.getRandomDecimal(80.56, 99.65)));
                        su.setCreateTime(createTime);
                        su.setUpdateTime(createTime);
                        data.add(su);
                        diyKey.remove();
                    } else if (StringUtils.isNotBlank(su.getContent()) && su.getContent().contains(keyword)) {
                        su.setLyrical("0");
                        su.setNegativeIndex(String.valueOf(DataUtil.getRandomDecimal(60.56, 90.65)));
                        su.setCreateTime(createTime);
                        su.setUpdateTime(createTime);
                        data.add(su);
                        diyKey.remove();
                    }
                }
            }
        }

        //第一阶梯负面数值
        Iterator<SearchResult> ifirst = unique.iterator();
        while (ifirst.hasNext()) {
            SearchResult su = ifirst.next();
            for (String aeg : firstLevel) {
                if (StringUtils.isNotBlank(su.getTitle()) && su.getTitle().contains(aeg)) {
                    su.setLyrical("0");
                    su.setNegativeIndex(String.valueOf(DataUtil.getRandomDecimal(71.56, 99.65)));
                    su.setCreateTime(createTime);
                    su.setUpdateTime(createTime);
                    data.add(su);
                    ifirst.remove();
                    break;
                }
                if (StringUtils.isNotBlank(su.getContent()) && su.getContent().contains(aeg)) {
                    su.setLyrical("0");
                    su.setNegativeIndex(String.valueOf(DataUtil.getRandomDecimal(71.56, 89.65)));
                    su.setCreateTime(createTime);
                    su.setUpdateTime(createTime);
                    data.add(su);
                    ifirst.remove();
                    break;
                }
            }
        }

        //第二阶梯负面数值
        Iterator<SearchResult> iscoend = unique.iterator();
        while (iscoend.hasNext()) {
            SearchResult su = iscoend.next();
            for (String aeg : firstLevel) {
                if (StringUtils.isNotBlank(su.getTitle()) && su.getTitle().contains(aeg)) {
                    su.setLyrical("0");
                    su.setNegativeIndex(String.valueOf(DataUtil.getRandomDecimal(51.23, 80.84)));
                    su.setCreateTime(createTime);
                    su.setUpdateTime(createTime);
                    data.add(su);
                    iscoend.remove();
                    break;
                }
                if (StringUtils.isNotBlank(su.getContent()) && su.getContent().contains(aeg)) {
                    su.setLyrical("0");
                    su.setNegativeIndex(String.valueOf(DataUtil.getRandomDecimal(51.23, 75.84)));
                    su.setCreateTime(createTime);
                    su.setUpdateTime(createTime);
                    data.add(su);
                    iscoend.remove();
                    break;
                }
            }
        }

        //第三阶梯负面数值
        Iterator<SearchResult> ithird = unique.iterator();
        while (ithird.hasNext()) {
            SearchResult su = ithird.next();
            for (String aeg : firstLevel) {
                if (StringUtils.isNotBlank(su.getTitle()) && su.getTitle().contains(aeg)) {
                    su.setLyrical("0");
                    su.setNegativeIndex(String.valueOf(DataUtil.getRandomDecimal(31.01, 59.32)));
                    su.setCreateTime(createTime);
                    su.setUpdateTime(createTime);
                    data.add(su);
                    ithird.remove();
                    break;
                }
                if (StringUtils.isNotBlank(su.getContent()) && su.getContent().contains(aeg)) {
                    su.setLyrical("0");
                    su.setNegativeIndex(String.valueOf(DataUtil.getRandomDecimal(31.01, 59.32)));
                    su.setCreateTime(createTime);
                    su.setUpdateTime(createTime);
                    data.add(su);
                    ithird.remove();
                    break;
                }
            }
        }

        //负面几乎为0
        int i = 0;
        for (SearchResult ru : unique) {
            if (i > 10) {
                break;
            }
            ru.setLyrical("1");
            ru.setNegativeIndex(String.valueOf(DataUtil.getRandomDecimal(0.01, 30.00)));
            ru.setCreateTime(createTime);
            ru.setUpdateTime(createTime);
            data.add(ru);
            i++;
        }

        //根据负面值排序
        data.sort(Collections.reverseOrder());
        return data;
    }

    public void setSpiderServices(List<SpiderService> spiderServices) {
        this.spiderServices = spiderServices;
    }
}
